package com.net.xpay.common.service.impl;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.invoice.DeliveryAddress;
import com.net.xpay.common.domain.invoice.Invoice;
import com.net.xpay.common.domain.invoice.InvoiceTitle;
import com.net.xpay.common.enums.invoice.DeliveryAddressType;
import com.net.xpay.common.enums.invoice.InvoiceMaterial;
import com.net.xpay.common.enums.invoice.InvoiceStatus;
import com.net.xpay.common.enums.invoice.OpenInvoiceStatus;
import com.net.xpay.core.constant.PoseidonErrorCode;
import com.net.xpay.core.domain.ChargeRecord;
import com.net.xpay.core.manager.ChargeRecordManager;
import com.net.xpay.core.model.DeliveryAddressModel;
import com.net.xpay.core.model.InvoiceModel;
import com.net.xpay.core.model.InvoiceTitleModel;
import com.net.xpay.core.model.OpenInvoiceModel;
import com.net.xpay.core.utils.BeanCopierUtil;
import com.net.xpay.core.validator.InvoiceTitleValidator;
import com.net.xpay.core.validator.InvoiceValidator;
import com.net.common.exception.BusinessException;
import com.net.common.util.PhoneUtil;
import com.net.xpay.common.enums.invoice.*;
import com.net.xpay.common.manager.invoice.DeliveryAddressManager;
import com.net.xpay.common.manager.invoice.InvoiceManager;
import com.net.xpay.common.manager.invoice.InvoiceTitleManager;
import com.net.xpay.common.service.InvoiceService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class InvoiceServiceImpl implements InvoiceService {

    @Autowired
    private InvoiceTitleManager invoiceTitleManager;

    @Autowired
    private DeliveryAddressManager deliveryAddressManager;

    @Autowired
    private InvoiceTitleValidator invoiceTitleValidator;

    @Autowired
    private InvoiceValidator invoiceValidator;

    @Autowired
    private InvoiceManager invoiceManager;

    @Autowired
    private ChargeRecordManager chargeRecordManager;


    @Override
    public void saveInvoiceTitle(InvoiceTitleModel model) {
        if (model == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "发票抬头信息不能为空");
        }
        invoiceTitleValidator.validateInvoiceTitle(model);
        InvoiceTitle invoiceTitle = new InvoiceTitle();
        BeanCopierUtil.copy(model, invoiceTitle);
        invoiceTitleManager.save(invoiceTitle);
    }

    @Override
    public void updateInvoiceTitle(InvoiceTitleModel model) {
        invoiceTitleValidator.validateInvoiceTitle(model);
        InvoiceTitle invoiceTitle = invoiceTitleManager.findById(model.getUserId(), model.getId());
        if (invoiceTitle == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "发票抬头不存在");
        }
        invoiceTitle.setInvoiceTitle(model.getInvoiceTitle());
        invoiceTitle.setInvoiceTitleType(model.getInvoiceTitleType());
        invoiceTitle.setInvoiceType(model.getInvoiceType());
        invoiceTitle.setAccountNo(model.getAccountNo());
        invoiceTitle.setAccountsBank(model.getAccountsBank());
        invoiceTitle.setRegisteredAddress(model.getRegisteredAddress());
        invoiceTitle.setTaxIdNumber(model.getTaxIdNumber());
        invoiceTitle.setRegisteredPhone(model.getRegisteredPhone());
        invoiceTitleManager.update(invoiceTitle);
    }

    @Override
    public List<InvoiceTitle> listInvoiceTitle(User merchant) {
        return invoiceTitleManager.listByUserId(merchant.getId());
    }

    @Override
    public void saveDeliveryAddress(DeliveryAddressModel model) {
        if (Strings.isNullOrEmpty(model.getRecipientName())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "收件人姓名不能为空");
        }
        if (Strings.isNullOrEmpty(model.getProvince())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "省份不能为空，请选择省份");
        }
        if (Strings.isNullOrEmpty(model.getCity())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "城市不能为空，请选择城市");
        }
        if (Strings.isNullOrEmpty(model.getDistrict())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "县区不能为空，请选择县区");
        }
        if (Strings.isNullOrEmpty(model.getDetailedAddress())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "详细地址不能为空");
        }
        if (Strings.isNullOrEmpty(model.getContactsPhone())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "联系人手机号不能为空");
        }
        if (!PhoneUtil.isEffectiveMobile(model.getContactsPhone())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "手机号格式不正确");
        }
        List<DeliveryAddress> list = deliveryAddressManager.listByUserId(model.getUserId());
        if (list.size() > 10) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "邮寄地址不能超过10个");
        }
        if (list.size() == 0) {
            DeliveryAddress newDeliveryAddress = new DeliveryAddress();
            newDeliveryAddress.setDeliveryAddressType(DeliveryAddressType.DEFAULT);
            BeanCopierUtil.copy(model, newDeliveryAddress);
            deliveryAddressManager.save(newDeliveryAddress);
        } else {
            DeliveryAddress deliveryAddress = new DeliveryAddress();
            deliveryAddress.setDeliveryAddressType(DeliveryAddressType.NON_DEFAULT);
            BeanCopierUtil.copy(model, deliveryAddress);
            deliveryAddressManager.save(deliveryAddress);
        }


    }

    @Override
    public List<DeliveryAddress> getDeliveryAddress(User merchant) {
        return deliveryAddressManager.listByUserId(merchant.getId());
    }

    @Override
    public void updateDeliveryAddress(DeliveryAddressModel model) {
        if (Strings.isNullOrEmpty(model.getRecipientName())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "收件人姓名不能为空");
        }
        if (Strings.isNullOrEmpty(model.getProvince())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "省份不能为空，请选择省份");
        }
        if (Strings.isNullOrEmpty(model.getCity())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "城市不能为空，请选择城市");
        }
        if (Strings.isNullOrEmpty(model.getDistrict())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "县区不能为空，请选择县区");
        }
        if (Strings.isNullOrEmpty(model.getDetailedAddress())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "详细地址不能为空");
        }
        if (Strings.isNullOrEmpty(model.getContactsPhone())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "联系人手机号不能为空");
        }
        if (!PhoneUtil.isEffectiveMobile(model.getContactsPhone())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "手机号格式不正确");
        }
        DeliveryAddress deliveryAddress = deliveryAddressManager.findById(model.getUserId(), model.getId());
        if (deliveryAddress == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "邮寄地址不能为空");
        }
        BeanCopierUtil.copy(model, deliveryAddress);
        deliveryAddressManager.update(deliveryAddress);
    }

    @Override
    @Transactional(transactionManager = "xpayCommonTransactionManager", rollbackFor = Exception.class)
    public void setAsDefaultDeliveryAddress(Long userId, Long id) {
        if (id == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "系统异常");
        }
        //设置用户的所有邮寄地址为非默认地址
        deliveryAddressManager.updateDeliveryAddressTypeAsNonDefault(userId);
        //设置当前地址为默认地址
        DeliveryAddress deliveryAddress = deliveryAddressManager.getById(id);
        if (deliveryAddress == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "邮寄地址不存在");
        }
        deliveryAddress.setDeliveryAddressType(DeliveryAddressType.DEFAULT);
        deliveryAddressManager.update(deliveryAddress);
    }

    @Override
    @Transactional(transactionManager = "xpayCommonTransactionManager", rollbackFor = Exception.class)
    public void deleteDeliveryAddress(Long userId, Long id) {
        Preconditions.checkArgument(id != null);
        DeliveryAddress deliveryAddress = deliveryAddressManager.findById(userId, id);
        if (deliveryAddress == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "邮寄地址不存在");
        }
        if (!deliveryAddress.getDeliveryAddressType().equals(DeliveryAddressType.DEFAULT)) {
            deliveryAddressManager.deleteById(id);
        } else {
            List<DeliveryAddress> list = deliveryAddressManager.listByUserId(userId);
            if (list.size() == 1) {
                deliveryAddressManager.deleteById(id);
                return;
            }
            deliveryAddressManager.deleteById(id);
            List<DeliveryAddress> deliveryAddressList = deliveryAddressManager.listByUserId(userId);
            DeliveryAddress address = deliveryAddressList.get(0);
            address.setDeliveryAddressType(DeliveryAddressType.DEFAULT);
            deliveryAddressManager.update(address);
        }
    }

    @Override
    public void addInvoice(Long userId, InvoiceModel model) {
        if (model.getInvoiceMaterial().equals(InvoiceMaterial.PAPER)) {
            invoiceValidator.validateSpecialPaperInvoice(model);
            Invoice paperInvoice = new Invoice();
            BeanCopierUtil.copy(model, paperInvoice);
            paperInvoice.setInvoiceStatus(InvoiceStatus.DEALING);
            paperInvoice.setUserId(userId);
            invoiceManager.save(paperInvoice);
        } else {
            invoiceValidator.validateSpecialInvoice(model);
            Invoice invoice = new Invoice();
            BeanCopierUtil.copy(model, invoice);
            invoice.setUserId(userId);
            invoice.setInvoiceStatus(InvoiceStatus.DEALING);
            invoice.setAccountNo("");
            invoice.setAccountsBank("");
            invoice.setRegisteredAddress("");
            invoice.setRegisteredPhone("");
            invoiceManager.save(invoice);
        }
        chargeRecordManager.updateOpenInvoiceStatusByIds(model.getChargeRecordIds(), OpenInvoiceStatus.DEALING);
    }

    @Override
    public void openInvoice(OpenInvoiceModel model) {
        if (model.getUserId() == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "用户编号不能为空");
        }
        if (model.getId() == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "发票编号不能为空");
        }
        if (Strings.isNullOrEmpty(model.getInvoiceNumber())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "发票号码不可为空");
        }
        //查询
        Invoice invoice = invoiceManager.findById(model.getUserId(), model.getId());
        if (invoice == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "发票不存在");
        }
        //查询充值记录
        List<Long> chargeRecordIds = invoice.getChargeRecordIds();
        if (CollectionUtils.isEmpty(chargeRecordIds)) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "未有充值记录,开票失败");
        }
        //更新充值记录状态
        chargeRecordManager.updateOpenInvoiceStatusByIds(chargeRecordIds, OpenInvoiceStatus.SUCCESS);
        //验证
        if (model.getInvoiceMaterial().equals(InvoiceMaterial.PAPER)) {
            if (Strings.isNullOrEmpty(model.getExpressNumber())) {
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "邮寄单号不可为空");
            }
            invoice.setInvoiceNumber(model.getInvoiceNumber());
            invoice.setExpressNumber(model.getExpressNumber());
            invoice.setMailedTime(LocalDateTime.now());
            invoice.setDealingTime(LocalDateTime.now());
            invoice.setInvoiceStatus(InvoiceStatus.MAILED);
            invoiceManager.update(invoice);
        } else {
            if (Strings.isNullOrEmpty(model.getInvoicePage())) {
                throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "电子发票图片不可为空");
            }
            invoice.setInvoiceNumber(model.getInvoiceNumber());
            invoice.setInvoiceUrl(model.getInvoicePage());
            invoice.setDealingTime(LocalDateTime.now());
            invoice.setInvoiceStatus(InvoiceStatus.SUCCESS);
            invoiceManager.update(invoice);
        }
    }

    @Override
    public void openInvoiceFail(OpenInvoiceModel model) {
        if (model.getUserId() == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "用户编号不能为空");
        }
        if (model.getId() == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "发票编号不能为空");
        }
        if (Strings.isNullOrEmpty(model.getFailMessage())) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "失败原因不能为空");
        }
        //查询
        Invoice invoice = invoiceManager.findById(model.getUserId(), model.getId());
        if (invoice == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "发票不存在");
        }
        //查询充值记录
        List<Long> chargeRecordIds = invoice.getChargeRecordIds();
        if (CollectionUtils.isEmpty(chargeRecordIds)) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "未有充值记录,开票失败");
        }

        chargeRecordManager.updateOpenInvoiceStatusByIds(chargeRecordIds, OpenInvoiceStatus.WAIT);

        invoice.setFailMessage(model.getFailMessage());
        invoice.setInvoiceStatus(InvoiceStatus.FAIL);
        invoice.setFailTime(LocalDateTime.now());
        invoiceManager.update(invoice);
    }

    @Override
    public List<ChargeRecord> listRelatedChargeRecord(Long userId, Long id) {
        Preconditions.checkArgument(id != null);
        Invoice invoice = invoiceManager.findById(userId, id);
        List<Long> recordIds = invoice.getChargeRecordIds();

        return chargeRecordManager.listByIds(recordIds);
    }

    @Override
    public List<ChargeRecord> adminListRelatedChargeRecord(Long id) {
        if (id == null) {
            throw new BusinessException(PoseidonErrorCode.PARAMETER_ILLEGAL, "未有充值记录");
        }
        Invoice invoice = invoiceManager.getById(id);
        List<Long> recordIds = invoice.getChargeRecordIds();

        return chargeRecordManager.listByIds(recordIds);
    }


}
